package lol.clann.bukkit.pluginboot.context;

import lol.clann.bukkit.pluginboot.model.ConfigWrapper;
import lol.clann.clannboot.context.BeanContext;
import lol.clann.clannboot.context.InjectContext;
import lol.clann.clannboot.context.ModuleContext;
import lol.clann.clannboot.module.inject.InjectorHolder;
import org.bukkit.Bukkit;
import org.bukkit.Server;
import org.bukkit.Warning;
import org.bukkit.command.ConsoleCommandSender;
import org.bukkit.help.HelpMap;
import org.bukkit.inventory.ItemFactory;
import org.bukkit.plugin.PluginManager;
import org.bukkit.plugin.RegisteredServiceProvider;
import org.bukkit.plugin.ServicesManager;
import org.bukkit.plugin.messaging.Messenger;
import org.bukkit.scheduler.BukkitScheduler;
import org.bukkit.scoreboard.ScoreboardManager;
import org.bukkit.util.CachedServerIcon;
import org.nutz.lang.Lang;

import java.util.function.Function;

/**
 * @author pyz
 * @date 2018/9/16 下午5:57
 */
public class InjectorRegister {


    static {
        try {
            Function<InjectorHolder, Object> func = null;

            // bukkit的Service
            func = (holder) -> {
                RegisteredServiceProvider<?> r = Bukkit.getServicesManager().getRegistration(holder.getField().getType());
                if (r == null) {
                    return null;
                }
                Object provider = r.getProvider();
                if (provider == null) {
                    return null;
                }
                // 做缓存
                BeanContext.registerBean(ModuleContext.rootModuleId, provider.getClass().getName(), provider);
                return provider;
            };

            InjectContext.registerInjector(ModuleContext.rootModuleId, ConfigWrapper.class
                    , (holder) -> {
                        ConfigWrapper cw = new ConfigWrapper(holder.getArgs()[0]);
                        cw.load();
                        return cw;
                    }, false);

            InjectContext.registerPredicateCreater(ModuleContext.rootModuleId,
                    ih -> {
                        RegisteredServiceProvider<?> r = Bukkit.getServicesManager().getRegistration(ih.getField().getType());
                        if (r == null) {
                            return false;
                        }
                        Object provider = r.getProvider();
                        if (provider == null) {
                            return false;
                        }
                        return true;
                    },
                    func, false);
            //Bukkit
            InjectContext.registerInjector(ModuleContext.rootModuleId, Server.class, (holder) -> Bukkit.getServer(), false);
            InjectContext.registerInjector(ModuleContext.rootModuleId, PluginManager.class, (holder) -> Bukkit.getPluginManager(), false);
            InjectContext.registerInjector(ModuleContext.rootModuleId, ItemFactory.class, (holder) -> Bukkit.getItemFactory(), false);
            InjectContext.registerInjector(ModuleContext.rootModuleId, BukkitScheduler.class, (holder) -> Bukkit.getScheduler(), false);
            InjectContext.registerInjector(ModuleContext.rootModuleId, ServicesManager.class, (holder) -> Bukkit.getServicesManager(), false);
            InjectContext.registerInjector(ModuleContext.rootModuleId, ConsoleCommandSender.class, (holder) -> Bukkit.getConsoleSender(), false);
            InjectContext.registerInjector(ModuleContext.rootModuleId, HelpMap.class, (holder) -> Bukkit.getHelpMap(), false);
            InjectContext.registerInjector(ModuleContext.rootModuleId, Warning.WarningState.class, (holder) -> Bukkit.getWarningState(), false);
            InjectContext.registerInjector(ModuleContext.rootModuleId, CachedServerIcon.class, (holder) -> Bukkit.getServerIcon(), false);
            InjectContext.registerInjector(ModuleContext.rootModuleId, ScoreboardManager.class, (holder) -> Bukkit.getScoreboardManager(), false);
            InjectContext.registerInjector(ModuleContext.rootModuleId, Messenger.class, (holder) -> Bukkit.getMessenger(), false);
        } catch (Throwable e) {
            throw Lang.wrapThrow(e);
        }
    }
}
